package com.xiaoxx.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxx.enums.ResdisKeyEnum;
import com.xiaoxx.mapper.SysRedisKeyMapper;
import com.xiaoxx.model.entity.sys.SysRedisKey;
import com.xiaoxx.model.vo.sys.SysRedisKeyVo;
import com.xiaoxx.service.SysRedisKeyService;
import com.xiaoxx.utils.BeanDtoVoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author HX
 * @since 2023-08-17
 */
@Service
public class SysRedisKeyServiceImpl extends ServiceImpl<SysRedisKeyMapper, SysRedisKey> implements SysRedisKeyService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostConstruct
    @Transactional
    public void addRedisEnums() {
        remove(null);
        List<SysRedisKey> adds = new ArrayList<>();
        for (ResdisKeyEnum value : ResdisKeyEnum.values()) {
            SysRedisKey sysRedisKey = new SysRedisKey();
            sysRedisKey.setRedisKey(value.getRedisKey());
            sysRedisKey.setRedisDesc(value.getRedisDesc());
            sysRedisKey.setCreateTime(LocalDateTime.now());
            sysRedisKey.setUpdateTime(LocalDateTime.now());
            adds.add(sysRedisKey);
        }
        if (!adds.isEmpty()) {
            saveBatch(adds);
        }
    }

    @Override
    public List<SysRedisKeyVo> listRedisKeys() {
        List<SysRedisKey> list = list();
        Set<String> keysWithPrefix = new HashSet<>();
        for (SysRedisKey sysRedisKey : list) {
            ScanOptions scanOptions = ScanOptions.scanOptions()
                    .match(sysRedisKey.getRedisKey() + "*")  // 匹配以指定前缀开头的 keys
                    .count(1)  // 每次扫描的数量
                    .build();
            redisTemplate.executeWithStickyConnection(connection -> {
                try (Cursor<byte[]> cursor = connection.scan(scanOptions)) {
                    while (cursor.hasNext()) {
                        byte[] keyBytes = cursor.next();
                        String key = new String(keyBytes);
                        keysWithPrefix.add(key.substring(0, key.indexOf(":")));  // 提取前缀部分
                    }
                }
                return null;
            });
        }
        list = list.stream().filter(i -> keysWithPrefix.contains(i.getRedisKey())).collect(Collectors.toList());
        return BeanDtoVoUtil.listVo(list, SysRedisKeyVo.class);
    }

    @Override
    public List<String> listRedisKeyNames(String key) {
        Set<String> keys = redisTemplate.keys(key.concat(":*"));
        List<String> list = new ArrayList<>(keys);
        return list;
    }

    @Override
    public Map<String, Object> getRedisValue(String key) {
        Map<String, Object> map = new HashMap<>();
        Object value = "";
        try {
            value = redisTemplate.opsForValue().get(key);
        } catch (RedisSystemException e) {
            try {
                value = redisTemplate.opsForList().range(key, 0, -1);
            } catch (RedisSystemException e1) {
                HashOperations<String, String, String> hash = redisTemplate.opsForHash();
                value = hash.entries(key);
            }
        }
        map.put("key", key);
        map.put("value", value);
        return map;
    }

    @Override
    public Boolean del(String key) {
        Set<String> keys = redisTemplate.keys(key);
        for (String redisKey : keys) {
            redisTemplate.delete(redisKey);
        }
        return true;
    }
}
